﻿using RakutenProxy.Model.NopCommerce;
using RakutenProxy.Model.Rakuten;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;

namespace RakutenProxy.DataConverter
{
    public class RakNopProductAttributeCombinationConverter : RakNopDataConverter<Model.Rakuten.ProductAttributeCombination, Model.NopCommerce.ProductVariantAttributeCombination>
    {
        public RakNopProductAttributeCombinationConverter(DbContext sourceDbContext, DbContext targetDbContext)
            : base(sourceDbContext, targetDbContext)
        {
        }

        protected override Model.NopCommerce.ProductVariantAttributeCombination GetObjectFromSource(Model.Rakuten.ProductAttributeCombination source)
        {
            var nopAttributeCombination = new Model.NopCommerce.ProductVariantAttributeCombination();

            var productAttributeCombination = Helper.ProductAttributeCombination.Deserialize(source.AttributesXml);

            var rakutenDbContext = (RakutenDbContext)SourceContext;

            var nopProductAttributeCombination = new Helper.ProductAttributeCombination();

            foreach (var attribute in productAttributeCombination.Attributes)
            {
                var nopAttribute = new Helper.ProductVariantAttribute();

                var rakAttributeId = attribute.ID;
                var nopAttributeId = rakutenDbContext.Rakuten_NopCommerce_ProductAttribute_Maps.First(m => m.RakutenProductAttributeId == rakAttributeId).NopCommerceProductAttributeId;

                nopAttribute.ID = nopAttributeId;

                var nopAttributeValueId = rakutenDbContext.Rakuten_NopCommerce_ProductAttribteValue_Maps.First(m => m.RakutenProductAttributeValueId == attribute.ProductVariantAttributeValue.Value);

                nopAttribute.ProductVariantAttributeValue = new Helper.ProductVariantAttributeValue { Value = nopAttributeValueId.NopCommerceProductAttributeValueId };

                nopProductAttributeCombination.Attributes.Add(nopAttribute);
            }

            var productMap = rakutenDbContext.Rakuten_NopCommerce_Product_Maps.First(m => m.RakutenProductId == source.ProductId);

            nopAttributeCombination.ProductId = productMap.NopCommerceProductId;
            nopAttributeCombination.AttributesXml = productAttributeCombination.Serialize();
            nopAttributeCombination.StockQuantity = source.IsStockAvailable ? 1000 : 0;

            return nopAttributeCombination;
        }

        protected override void UpdateObjectFromSource(Model.NopCommerce.ProductVariantAttributeCombination target, Model.Rakuten.ProductAttributeCombination source)
        {
            // No update available
        }

        public override void Migrate()
        {
            var rakDbContext = (RakutenDbContext)SourceContext;
            var nopDbContext = (NopCommerceEntities)TargetContext;

            var mappedRakutenIds = rakDbContext.Rakuten_NopCommerce_ProductAttributeCombination_Maps.Select(m => m.RakutenProductAttributeCombinationId);
            var notMappedCombinations = rakDbContext.ProductAttributeCombinations.Where(a => !mappedRakutenIds.Contains(a.Id));

            foreach (var combination in notMappedCombinations)
            {
                var nopCombination = GetObjectFromSource(combination);
                nopDbContext.ProductVariantAttributeCombinations.Add(nopCombination);
                nopDbContext.SaveChanges();
                var map = new Rakuten_NopCommerce_ProductAttributeCombination_Map { RakutenProductAttributeCombinationId = combination.Id, NopCommerceProductAttributeCombinationId = nopCombination.Id };
                rakDbContext.Rakuten_NopCommerce_ProductAttributeCombination_Maps.Add(map);
            }

            rakDbContext.SaveChanges();
            nopDbContext.SaveChanges();
        }

        public override void MigrateOneRecord(int id)
        {
            var rakDbContext = (RakutenDbContext)SourceContext;
            var nopDbContext = (NopCommerceEntities)TargetContext;

            var rakAttributeCombination = rakDbContext.ProductAttributeCombinations.FirstOrDefault(c => c.Id == id);
            if (rakAttributeCombination == null)
                return;

            var map = rakDbContext.Rakuten_NopCommerce_ProductAttributeCombination_Maps.FirstOrDefault(m => m.RakutenProductAttributeCombinationId == id);
            if (map == null)
            {
                var nopCombination = GetObjectFromSource(rakAttributeCombination);
                nopDbContext.ProductVariantAttributeCombinations.Add(nopCombination);
                nopDbContext.SaveChanges();

                map = new Rakuten_NopCommerce_ProductAttributeCombination_Map { RakutenProductAttributeCombinationId = rakAttributeCombination.Id, NopCommerceProductAttributeCombinationId = nopCombination.Id };
                rakDbContext.Rakuten_NopCommerce_ProductAttributeCombination_Maps.Add(map);
                rakDbContext.SaveChanges();
            }
        }


        public override void RemoveOneRecord(int id)
        {
            var rakDbContext = (RakutenDbContext)SourceContext;
            var nopDbContext = (NopCommerceEntities)TargetContext;

            var map = rakDbContext.Rakuten_NopCommerce_ProductAttributeCombination_Maps.FirstOrDefault(m => m.RakutenProductAttributeCombinationId == id);
            if (map == null)
                return;

            var nopCombination = nopDbContext.ProductVariantAttributeCombinations.FirstOrDefault(c => c.Id == map.NopCommerceProductAttributeCombinationId);
            if (nopCombination != null)
            {
                nopDbContext.ProductVariantAttributeCombinations.Remove(nopCombination);
            }

            rakDbContext.Rakuten_NopCommerce_ProductAttributeCombination_Maps.Remove(map);

            rakDbContext.SaveChanges();
            nopDbContext.SaveChanges();
        }
    }
}